package com.bjpowernode.seckillservice.listener;

import com.bjpowernode.constant.Constants;
import com.bjpowernode.entity.Orders;
import com.bjpowernode.seckillservice.service.OrderService;
import com.bjpowernode.seckillservice.service.impl.DelayMessageService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import jakarta.annotation.Resource;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 下单消费者
 */
@Component
public class OrderListener {

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private OrderService orderService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private DelayMessageService delayMessageService;

    /**
     * 监听下单队列
     * 1. 获取Orders消息 将其json格式转为Orders对象
     * 2. 调用OrderService.doOrder方法
     * 3. 成功则将订单结果保存到Redis中 限制同一个商品1个用户只能秒杀1次
     * 4. 手动签收
     * 5. 发送延迟消息   检查用户是否在执行时间内支付
     * @param message
     */
    @RabbitListener(queues = Constants.QUEUE_NAME_ORDER,concurrency = "6")
    public void onMessage(Message message, Channel channel)  {
        //获取消息标签
        long tag = message.getMessageProperties().getDeliveryTag();
        try {
            //1. 获取Orders消息 将其json格式转为Orders对象
            Orders orders = objectMapper.readValue(message.getBody(), Orders.class);

            //2. 调用OrderService.doOrder方法
            int orderResult = orderService.doOrder(orders);

            if (orderResult == 1) {
                //3. 成功则将订单结果保存到Redis中 限制同一个商品1个用户只能秒杀1次
                //key 商品id和用户id   value 订单对象
                redisTemplate.opsForValue().set(Constants.REDIS_RESULT + orders.getGoodsId() + ":" + orders.getUid(), orders);

                //4. 手动签收
                channel.basicAck(tag, false);

                //5. 发送延迟消息   检查用户是否在执行时间内支付
                delayMessageService.sendDelayMessage(orders.getId());


                return;
            }

            //不签收
            channel.basicNack(tag, false, true);

        } catch (IOException e) {

            //不签收
            try {
                channel.basicNack(tag, false, true);
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }

            throw new RuntimeException(e);


        }


    }
}
